/*=====================================================
 Critical Links
 Auto Configuration Server

 Authors:
 Rui Eduardo Gouveia Gil - r-gil@critical-links.com

 Date: 2010
 Version 0.1
 =======================================================*/
#include "database/DataBase.h"
#include "ACSConfig.h"

namespace acs
{

DataBase::~DataBase()
{
	LOG_INFO_STR("Deleting DataBase...");

	sqlite3_close(dbFile);
	sqlite3_shutdown();

	LOG_INFO_STR("DataBase deleted");
}

Configuration DataBase::createConfiguration(const Configuration& configuration)
{
	char buffer[4096];
	sprintf(buffer,"INSERT INTO configuration(rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,configuration.isRWan());
	this->setIntToStatement(stmt,2,configuration.isRUsers());
	this->setStringToStatement(stmt,3,configuration.getName());
	this->setIntToStatement(stmt,4,current);
	this->setIntToStatement(stmt,5,current);
	this->setStringToStatement(stmt,6,configuration.getDescription());
	this->setStringToStatement(stmt,7,configuration.getConfigFileName());
	this->setStringToStatement(stmt,8,configuration.getSHA());
	this->setStringToStatement(stmt,9,configuration.getCFType());
	this->setStringToStatement(stmt,10,configuration.getCFReboot());
	this->setStringToStatement(stmt,11,configuration.getCFRelease());
	this->setStringToStatement(stmt,12,configuration.getCFCreation());
	this->setStringToStatement(stmt,13,configuration.getCFLicenseID());
	this->setStringToStatement(stmt,14,configuration.getCFVoipSounds());
	this->setStringToStatement(stmt,15,configuration.getCFDescription());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return this->getConfiguration(configuration.getName());
}

void DataBase::updateConfiguration(const Configuration& configuration)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE configuration SET rwan=?, rusers=?, name=?, creation=?, updated=?, description=?, configFileName=?, SHA=?, cfType=?, cfReboot=?, cfRelease=?, cfCreation=?, cfLicenseID=?, cfVoipSounds=?, cfDescription=? WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,configuration.isRWan());
	this->setIntToStatement(stmt,2,configuration.isRUsers());
	this->setStringToStatement(stmt,3,configuration.getName());
	this->setIntToStatement(stmt,4,configuration.getCreation());
	this->setIntToStatement(stmt,5,current);
	this->setStringToStatement(stmt,6,configuration.getDescription());
	this->setStringToStatement(stmt,7,configuration.getConfigFileName());
	this->setStringToStatement(stmt,8,configuration.getSHA());
	this->setStringToStatement(stmt,9,configuration.getCFType());
	this->setStringToStatement(stmt,10,configuration.getCFReboot());
	this->setStringToStatement(stmt,11,configuration.getCFRelease());
	this->setStringToStatement(stmt,12,configuration.getCFCreation());
	this->setStringToStatement(stmt,13,configuration.getCFLicenseID());
	this->setStringToStatement(stmt,14,configuration.getCFVoipSounds());
	this->setStringToStatement(stmt,15,configuration.getCFDescription());
	this->setIntToStatement(stmt,16,configuration.getID());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

bool DataBase::existsConfiguration(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM configuration WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

bool DataBase::existsConfiguration(const std::string& name)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM configuration WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

Configuration DataBase::getConfiguration(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription FROM configuration WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	Configuration configuration;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Configuration not found."));
	}
	else if(result == SQLITE_ROW)
	{
		configuration.setID(sqlite3_column_int(stmt,0));
		configuration.setRWan(sqlite3_column_int(stmt,1));
		configuration.setRUsers(sqlite3_column_int(stmt,2));
		configuration.setName(std::string((char*)sqlite3_column_text(stmt,3)));
		configuration.setCreation(sqlite3_column_int(stmt,4));
		configuration.setUpdated(sqlite3_column_int(stmt,5));
		configuration.setDescription(std::string((char*)sqlite3_column_text(stmt,6)));
		configuration.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,7)));
		configuration.setSHA(std::string((char*)sqlite3_column_text(stmt,8)));
		configuration.setCFType(std::string((char*)sqlite3_column_text(stmt,9)));
		configuration.setCFReboot(std::string((char*)sqlite3_column_text(stmt,10)));
		configuration.setCFRelease(std::string((char*)sqlite3_column_text(stmt,11)));
		configuration.setCFCreation(std::string((char*)sqlite3_column_text(stmt,12)));
		configuration.setCFLicenseID(std::string((char*)sqlite3_column_text(stmt,13)));
		configuration.setCFVoipSounds(std::string((char*)sqlite3_column_text(stmt,14)));
		configuration.setCFDescription(std::string((char*)sqlite3_column_text(stmt,15)));
		configuration.setCommands(this->getConfigurationCommands(configuration.getID()));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return configuration;
}

Configuration DataBase::getConfiguration(const std::string& name)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id,rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription FROM configuration WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	int result = sqlite3_step(stmt);

	Configuration configuration;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Configuration not found."));
	}
	else if(result == SQLITE_ROW)
	{
		configuration.setID(sqlite3_column_int(stmt,0));
		configuration.setRWan(sqlite3_column_int(stmt,1));
		configuration.setRUsers(sqlite3_column_int(stmt,2));
		configuration.setName(std::string((char*)sqlite3_column_text(stmt,3)));
		configuration.setCreation(sqlite3_column_int(stmt,4));
		configuration.setUpdated(sqlite3_column_int(stmt,5));
		configuration.setDescription(std::string((char*)sqlite3_column_text(stmt,6)));
		configuration.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,7)));
		configuration.setSHA(std::string((char*)sqlite3_column_text(stmt,8)));
		configuration.setCFType(std::string((char*)sqlite3_column_text(stmt,9)));
		configuration.setCFReboot(std::string((char*)sqlite3_column_text(stmt,10)));
		configuration.setCFRelease(std::string((char*)sqlite3_column_text(stmt,11)));
		configuration.setCFCreation(std::string((char*)sqlite3_column_text(stmt,12)));
		configuration.setCFLicenseID(std::string((char*)sqlite3_column_text(stmt,13)));
		configuration.setCFVoipSounds(std::string((char*)sqlite3_column_text(stmt,14)));
		configuration.setCFDescription(std::string((char*)sqlite3_column_text(stmt,15)));
		configuration.setCommands(this->getConfigurationCommands(configuration.getID()));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return configuration;
}

std::vector<Configuration> DataBase::listConfigurations(const std::string& text)
{
	char buffer[2048];
	if(text.empty())
		sprintf(buffer,"SELECT id,rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription FROM configuration ORDER BY name");
	else
		sprintf(buffer,"SELECT id,rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription FROM configuration WHERE (LOWER(name) LIKE ? OR LOWER(cfRelease) LIKE ? OR LOWER(description) LIKE ?) ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	if(!text.empty())
	{
		std::string str = std::string("%") + text + std::string("%");
		std::transform(str.begin(),str.end(),str.begin(),::tolower);

		this->setStringToStatement(stmt,1,str);
		this->setStringToStatement(stmt,2,str);
		this->setStringToStatement(stmt,3,str);
	}

	int result;
	std::vector<Configuration> configurations;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Configuration configuration;
			configuration.setID(sqlite3_column_int(stmt,0));
			configuration.setRWan(sqlite3_column_int(stmt,1));
			configuration.setRUsers(sqlite3_column_int(stmt,2));
			configuration.setName(std::string((char*)sqlite3_column_text(stmt,3)));
			configuration.setCreation(sqlite3_column_int(stmt,4));
			configuration.setUpdated(sqlite3_column_int(stmt,5));
			configuration.setDescription(std::string((char*)sqlite3_column_text(stmt,6)));
			configuration.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,7)));
			configuration.setSHA(std::string((char*)sqlite3_column_text(stmt,8)));
			configuration.setCFType(std::string((char*)sqlite3_column_text(stmt,9)));
			configuration.setCFReboot(std::string((char*)sqlite3_column_text(stmt,10)));
			configuration.setCFRelease(std::string((char*)sqlite3_column_text(stmt,11)));
			configuration.setCFCreation(std::string((char*)sqlite3_column_text(stmt,12)));
			configuration.setCFLicenseID(std::string((char*)sqlite3_column_text(stmt,13)));
			configuration.setCFVoipSounds(std::string((char*)sqlite3_column_text(stmt,14)));
			configuration.setCFDescription(std::string((char*)sqlite3_column_text(stmt,15)));
			configuration.setCommands(this->getConfigurationCommands(configuration.getID()));
			configurations.push_back(configuration);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return configurations;
}

void DataBase::removeConfiguration(const int id)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		this->removeConfigurationCommands(id);

		char buffer[512];
		sprintf(buffer,"DELETE FROM configuration WHERE id=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::addConfigurationCommand(const Command& command)
{
	char buffer[2048];
	sprintf(buffer,"INSERT INTO configurationCommand(id,cindex,command,arguments) VALUES(?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,2048,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,command.getID());
	this->setIntToStatement(stmt,2,this->nextConfigurationCommands(command.getID()));
	this->setStringToStatement(stmt,3,command.getCommand());
	std::string arguments = command.argumentsToString();
	this->setStringToStatement(stmt,4,arguments);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::updateConfigurationCommand(const Command& command)
{
	char buffer[2048];
	sprintf(buffer,"UPDATE configurationCommand SET command=?, arguments=? where id=? AND cindex=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,2048,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setStringToStatement(stmt,1,command.getCommand());
	std::string arguments = command.argumentsToString();
	this->setStringToStatement(stmt,2,arguments);
	this->setIntToStatement(stmt,3,command.getID());
	this->setIntToStatement(stmt,4,command.getIndex());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

Command DataBase::getConfigurationCommands(const int id, const unsigned int cindex)
{
	char buffer[512];
	sprintf(buffer,"SELECT command,arguments FROM configurationCommand WHERE id=? AND cindex=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	Command command;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Configuration command not found."));
	}
	else if(result == SQLITE_ROW)
	{
		command.setID(id);
		command.setIndex(cindex);
		command.setCommand(std::string((char*)sqlite3_column_text(stmt,0)));
		command.argumentsFromString(std::string((char*)sqlite3_column_text(stmt,1)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return command;
}

std::vector<Command> DataBase::getConfigurationCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT cindex,command,arguments FROM configurationCommand WHERE id=? ORDER BY cindex");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result;
	std::vector<Command> commands;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Command command;
			command.setID(id);
			command.setIndex(sqlite3_column_int(stmt,0));
			command.setCommand(std::string((char*)sqlite3_column_text(stmt,1)));
			command.argumentsFromString(std::string((char*)sqlite3_column_text(stmt,2)));
			commands.push_back(command);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	return commands;
}

void DataBase::switchConfigurationCommandIndex(const int id, const unsigned int cindex1, const unsigned int cindex2)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		char buffer[512];
		sprintf(buffer,"UPDATE configurationCommand SET cindex=? WHERE id=? AND cindex=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,((unsigned int)-1));
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,cindex1);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE configurationCommand SET cindex=? WHERE id=? AND cindex=?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,cindex1);
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,cindex2);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE configurationCommand SET cindex=? WHERE id=? AND cindex=?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,cindex2);
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,((unsigned int)-1));

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::removeConfigurationCommand(const int id, const unsigned int cindex)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		char buffer[512];
		sprintf(buffer,"DELETE FROM configurationCommand WHERE id=? AND cindex=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);
		this->setIntToStatement(stmt,2,cindex);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE configurationCommand SET cindex=cindex-1 WHERE id=? AND cindex>?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);
		this->setIntToStatement(stmt,2,cindex);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::removeConfigurationCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM configurationCommand WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

Group DataBase::createGroup(const Group& group)
{
	char buffer[4096];
	sprintf(buffer,"INSERT INTO dgroup(name,creation,updated,description) VALUES(?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setStringToStatement(stmt,1,group.getName());
	this->setIntToStatement(stmt,2,current);
	this->setIntToStatement(stmt,3,current);
	this->setStringToStatement(stmt,4,group.getDescription());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return this->getGroup(group.getName());
}

void DataBase::updateGroup(const Group& group)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE dgroup SET name=?, creation=?, updated=?, description=? WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setStringToStatement(stmt,1,group.getName());
	this->setIntToStatement(stmt,2,group.getCreation());
	this->setIntToStatement(stmt,3,current);
	this->setStringToStatement(stmt,4,group.getDescription());
	this->setIntToStatement(stmt,5,group.getID());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

bool DataBase::existsGroup(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM dgroup WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

bool DataBase::existsGroup(const std::string& name)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM dgroup WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

Group DataBase::getGroup(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,name,creation,updated,description FROM dgroup WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	Group group;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Group not found."));
	}
	else if(result == SQLITE_ROW)
	{
		group.setID(sqlite3_column_int(stmt,0));
		group.setName(std::string((char*)sqlite3_column_text(stmt,1)));
		group.setCreation(sqlite3_column_int(stmt,2));
		group.setUpdated(sqlite3_column_int(stmt,3));
		group.setDescription(std::string((char*)sqlite3_column_text(stmt,4)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return group;
}

Group DataBase::getGroup(const std::string& name)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id,name,creation,updated,description FROM dgroup WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	int result = sqlite3_step(stmt);

	Group group;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Group not found."));
	}
	else if(result == SQLITE_ROW)
	{
		group.setID(sqlite3_column_int(stmt,0));
		group.setName(std::string((char*)sqlite3_column_text(stmt,1)));
		group.setCreation(sqlite3_column_int(stmt,2));
		group.setUpdated(sqlite3_column_int(stmt,3));
		group.setDescription(std::string((char*)sqlite3_column_text(stmt,4)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return group;
}

std::vector<Group> DataBase::listGroups(const std::string& text)
{
	char buffer[1024];
	if(text.empty())
		sprintf(buffer,"SELECT id,name,creation,updated,description FROM dgroup ORDER BY name");
	else
		sprintf(buffer,"SELECT id,name,creation,updated,description FROM dgroup WHERE (LOWER(name) LIKE ? OR LOWER(description) LIKE ?) ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	if(!text.empty())
	{
		std::string str = std::string("%") + text + std::string("%");
		std::transform(str.begin(),str.end(),str.begin(),::tolower);

		this->setStringToStatement(stmt,1,str);
		this->setStringToStatement(stmt,2,str);
		this->setStringToStatement(stmt,3,str);
	}

	int result;
	std::vector<Group> groups;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Group group;
			group.setID(sqlite3_column_int(stmt,0));
			group.setName(std::string((char*)sqlite3_column_text(stmt,1)));
			group.setCreation(sqlite3_column_int(stmt,2));
			group.setUpdated(sqlite3_column_int(stmt,3));
			group.setDescription(std::string((char*)sqlite3_column_text(stmt,4)));
			groups.push_back(group);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return groups;
}

void DataBase::removeGroup(const int id)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM dgroup WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

Device DataBase::createDevice(const Device& device)
{
	char buffer[4096];
	sprintf(buffer,"INSERT INTO device(groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,device.getGroupID());
	this->setIntToStatement(stmt,2,device.getConfigID());
	this->setIntToStatement(stmt,3,device.getRestoreConfigID());
	this->setIntToStatement(stmt,4,device.getConfigMode());
	this->setIntToStatement(stmt,5,device.getStatus());
	this->setIntToStatement(stmt,6,current);
	this->setIntToStatement(stmt,7,current);
	this->setIntToStatement(stmt,8,device.getContacted());
	this->setIntToStatement(stmt,9,device.getLastBackup());
	this->setIntToStatement(stmt,10,device.getLastRestore());
	this->setIntToStatement(stmt,11,device.getLocalChange());
	this->setStringToStatement(stmt,12,device.getIp());
	this->setStringToStatement(stmt,13,device.getSHA());
	this->setStringToStatement(stmt,14,device.getName());
	this->setStringToStatement(stmt,15,device.getDescription());
	this->setStringToStatement(stmt,16,device.getActionPeriod());
	this->setStringToStatement(stmt,17,device.getConfigFileName());
	this->setStringToStatement(stmt,18,device.getBuild());
	this->setStringToStatement(stmt,19,device.getUpTime());
	this->setStringToStatement(stmt,20,device.getRelease());
	this->setStringToStatement(stmt,21,device.getSwapUsed());
	this->setStringToStatement(stmt,22,device.getMaxUsers());
	this->setStringToStatement(stmt,23,device.getLicenseID());
	this->setStringToStatement(stmt,24,device.getSystemLoad());
	this->setStringToStatement(stmt,25,device.getGuiVersion());
	this->setStringToStatement(stmt,26,device.getFreeMemory());
	this->setStringToStatement(stmt,27,device.getPepsVersion());
	this->setStringToStatement(stmt,28,device.getCustomerName());
	this->setStringToStatement(stmt,29,device.getPartitionVar());
	this->setStringToStatement(stmt,30,device.getPartitionRoot());
	this->setStringToStatement(stmt,31,device.getPartitionHome());
	this->setStringToStatement(stmt,32,device.getInstalledMemory());
	this->setStringToStatement(stmt,33,device.getHardwareDescription());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return this->getDevice(device.getName());
}

void DataBase::updateDevice(const Device& device)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE device SET groupID=?, configID=?, lastRestoreConfigID=?, configMode=?, status=?, creation=?, updated=?, contacted=?, lastBackup=?, lastRestore=?, localChange=?, ip=?, SHA=?, name=?, description=?, actionPeriod=?, configFileName=?, build=?, upTime=?, release=?, swapUsed=?, maxUsers=?, licenseID=?, systemLoad=?, guiVersion=?, freeMemory=?, pepsVersion=?, customerName=?, partitionVar=?, partitionRoot=?, partitionHome=?, installedMemory=?, hardwareDescription=? WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,device.getGroupID());
	this->setIntToStatement(stmt,2,device.getConfigID());
	this->setIntToStatement(stmt,3,device.getRestoreConfigID());
	this->setIntToStatement(stmt,4,device.getConfigMode());
	this->setIntToStatement(stmt,5,device.getStatus());
	this->setIntToStatement(stmt,6,device.getCreation());
	this->setIntToStatement(stmt,7,current);
	this->setIntToStatement(stmt,8,device.getContacted());
	this->setIntToStatement(stmt,9,device.getLastBackup());
	this->setIntToStatement(stmt,10,device.getLastRestore());
	this->setIntToStatement(stmt,11,device.getLocalChange());
	this->setStringToStatement(stmt,12,device.getIp());
	this->setStringToStatement(stmt,13,device.getSHA());
	this->setStringToStatement(stmt,14,device.getName());
	this->setStringToStatement(stmt,15,device.getDescription());
	this->setStringToStatement(stmt,16,device.getActionPeriod());
	this->setStringToStatement(stmt,17,device.getConfigFileName());
	this->setStringToStatement(stmt,18,device.getBuild());
	this->setStringToStatement(stmt,19,device.getUpTime());
	this->setStringToStatement(stmt,20,device.getRelease());
	this->setStringToStatement(stmt,21,device.getSwapUsed());
	this->setStringToStatement(stmt,22,device.getMaxUsers());
	this->setStringToStatement(stmt,23,device.getLicenseID());
	this->setStringToStatement(stmt,24,device.getSystemLoad());
	this->setStringToStatement(stmt,25,device.getGuiVersion());
	this->setStringToStatement(stmt,26,device.getFreeMemory());
	this->setStringToStatement(stmt,27,device.getPepsVersion());
	this->setStringToStatement(stmt,28,device.getCustomerName());
	this->setStringToStatement(stmt,29,device.getPartitionVar());
	this->setStringToStatement(stmt,30,device.getPartitionRoot());
	this->setStringToStatement(stmt,31,device.getPartitionHome());
	this->setStringToStatement(stmt,32,device.getInstalledMemory());
	this->setStringToStatement(stmt,33,device.getHardwareDescription());
	this->setIntToStatement(stmt,34,device.getID());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::updateContact(const Device& device)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE device SET groupID=?, configID=?, lastRestoreConfigID=?, configMode=?, status=?, creation=?, updated=?, contacted=?, lastBackup=?, lastRestore=?, localChange=?, ip=?, SHA=?, name=?, description=?, actionPeriod=?, configFileName=?, build=?, upTime=?, release=?, swapUsed=?, maxUsers=?, licenseID=?, systemLoad=?, guiVersion=?, freeMemory=?, pepsVersion=?, customerName=?, partitionVar=?, partitionRoot=?, partitionHome=?, installedMemory=?, hardwareDescription=? WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,device.getGroupID());
	this->setIntToStatement(stmt,2,device.getConfigID());
	this->setIntToStatement(stmt,3,device.getRestoreConfigID());
	this->setIntToStatement(stmt,4,device.getConfigMode());
	this->setIntToStatement(stmt,5,device.getStatus());
	this->setIntToStatement(stmt,6,device.getCreation());
	this->setIntToStatement(stmt,7,device.getUpdated());
	this->setIntToStatement(stmt,8,current);
	this->setIntToStatement(stmt,9,device.getLastBackup());
	this->setIntToStatement(stmt,10,device.getLastRestore());
	this->setIntToStatement(stmt,11,device.getLocalChange());
	this->setStringToStatement(stmt,12,device.getIp());
	this->setStringToStatement(stmt,13,device.getSHA());
	this->setStringToStatement(stmt,14,device.getName());
	this->setStringToStatement(stmt,15,device.getDescription());
	this->setStringToStatement(stmt,16,device.getActionPeriod());
	this->setStringToStatement(stmt,17,device.getConfigFileName());
	this->setStringToStatement(stmt,18,device.getBuild());
	this->setStringToStatement(stmt,19,device.getUpTime());
	this->setStringToStatement(stmt,20,device.getRelease());
	this->setStringToStatement(stmt,21,device.getSwapUsed());
	this->setStringToStatement(stmt,22,device.getMaxUsers());
	this->setStringToStatement(stmt,23,device.getLicenseID());
	this->setStringToStatement(stmt,24,device.getSystemLoad());
	this->setStringToStatement(stmt,25,device.getGuiVersion());
	this->setStringToStatement(stmt,26,device.getFreeMemory());
	this->setStringToStatement(stmt,27,device.getPepsVersion());
	this->setStringToStatement(stmt,28,device.getCustomerName());
	this->setStringToStatement(stmt,29,device.getPartitionVar());
	this->setStringToStatement(stmt,30,device.getPartitionRoot());
	this->setStringToStatement(stmt,31,device.getPartitionHome());
	this->setStringToStatement(stmt,32,device.getInstalledMemory());
	this->setStringToStatement(stmt,33,device.getHardwareDescription());
	this->setIntToStatement(stmt,34,device.getID());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::resetDeviceSHA(const int id)
{
	char buffer[512];
	sprintf(buffer,"UPDATE device SET SHA=\"\" WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

bool DataBase::existsDevice(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM device WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

bool DataBase::existsDevice(const std::string& name)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM device WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

bool DataBase::existsDeviceWithLicense(const std::string& license)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM device WHERE LOWER(licenseID)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = license;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

Device DataBase::getDevice(const int id)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	Device device;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Device not found."));
	}
	else if(result == SQLITE_ROW)
	{
		device.setID(sqlite3_column_int(stmt,0));
		device.setGroupID(sqlite3_column_int(stmt,1));
		device.setConfigID(sqlite3_column_int(stmt,2));
		device.setRestoreConfigID(sqlite3_column_int(stmt,3));
		device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
		device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
		device.setCreation(sqlite3_column_int(stmt,6));
		device.setUpdated(sqlite3_column_int(stmt,7));
		device.setContacted(sqlite3_column_int(stmt,8));
		device.setLastBackup(sqlite3_column_int(stmt,9));
		device.setLastRestore(sqlite3_column_int(stmt,10));
		device.setLocalChange(sqlite3_column_int(stmt,11));
		device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
		device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
		device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
		device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
		device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
		device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
		device.setCommands(this->getDeviceCommands(device.getID()));
		device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
		device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
		device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
		device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
		device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
		device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
		device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
		device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
		device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
		device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
		device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
		device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
		device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
		device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
		device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
		device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return device;
}

Device DataBase::getDevice(const std::string& name)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE LOWER(name)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	std::string str = name;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	int result = sqlite3_step(stmt);

	Device device;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Device not found."));
	}
	else if(result == SQLITE_ROW)
	{
		device.setID(sqlite3_column_int(stmt,0));
		device.setGroupID(sqlite3_column_int(stmt,1));
		device.setConfigID(sqlite3_column_int(stmt,2));
		device.setRestoreConfigID(sqlite3_column_int(stmt,3));
		device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
		device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
		device.setCreation(sqlite3_column_int(stmt,6));
		device.setUpdated(sqlite3_column_int(stmt,7));
		device.setContacted(sqlite3_column_int(stmt,8));
		device.setLastBackup(sqlite3_column_int(stmt,9));
		device.setLastRestore(sqlite3_column_int(stmt,10));
		device.setLocalChange(sqlite3_column_int(stmt,11));
		device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
		device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
		device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
		device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
		device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
		device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
		device.setCommands(this->getDeviceCommands(device.getID()));
		device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
		device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
		device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
		device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
		device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
		device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
		device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
		device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
		device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
		device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
		device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
		device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
		device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
		device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
		device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
		device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return device;
}

Device DataBase::getDeviceWithLicense(const std::string& license)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE LOWER(licenseID)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	std::string str = license;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	int result = sqlite3_step(stmt);

	Device device;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Device not found."));
	}
	else if(result == SQLITE_ROW)
	{
		device.setID(sqlite3_column_int(stmt,0));
		device.setGroupID(sqlite3_column_int(stmt,1));
		device.setConfigID(sqlite3_column_int(stmt,2));
		device.setRestoreConfigID(sqlite3_column_int(stmt,3));
		device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
		device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
		device.setCreation(sqlite3_column_int(stmt,6));
		device.setUpdated(sqlite3_column_int(stmt,7));
		device.setContacted(sqlite3_column_int(stmt,8));
		device.setLastBackup(sqlite3_column_int(stmt,9));
		device.setLastRestore(sqlite3_column_int(stmt,10));
		device.setLocalChange(sqlite3_column_int(stmt,11));
		device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
		device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
		device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
		device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
		device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
		device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
		device.setCommands(this->getDeviceCommands(device.getID()));
		device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
		device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
		device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
		device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
		device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
		device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
		device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
		device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
		device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
		device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
		device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
		device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
		device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
		device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
		device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
		device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return device;
}

std::vector<Device> DataBase::getLastAccessDevices(unsigned int limit)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device ORDER BY contacted DESC LIMIT ?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	this->setIntToStatement(stmt,1,limit);

	int result;
	std::vector<Device> devices;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Device device;
			device.setID(sqlite3_column_int(stmt,0));
			device.setGroupID(sqlite3_column_int(stmt,1));
			device.setConfigID(sqlite3_column_int(stmt,2));
			device.setRestoreConfigID(sqlite3_column_int(stmt,3));
			device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
			device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
			device.setCreation(sqlite3_column_int(stmt,6));
			device.setUpdated(sqlite3_column_int(stmt,7));
			device.setContacted(sqlite3_column_int(stmt,8));
			device.setLastBackup(sqlite3_column_int(stmt,9));
			device.setLastRestore(sqlite3_column_int(stmt,10));
			device.setLocalChange(sqlite3_column_int(stmt,11));
			device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
			device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
			device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
			device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
			device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
			device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
			device.setCommands(this->getDeviceCommands(device.getID()));
			device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
			device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
			device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
			device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
			device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
			device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
			device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
			device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
			device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
			device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
			device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
			device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
			device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
			device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
			device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
			device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
			devices.push_back(device);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return devices;
}

std::vector<Device> DataBase::listDevices(const std::string& text)
{
	char buffer[1024];
	if(text.empty())
		sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device ORDER BY name");
	else
		sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE (LOWER(name) LIKE ? OR LOWER(release) LIKE ? OR LOWER(description) LIKE ?) ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	if(!text.empty())
	{
		std::string str = std::string("%") + text + std::string("%");
		std::transform(str.begin(),str.end(),str.begin(),::tolower);

		this->setStringToStatement(stmt,1,str);
		this->setStringToStatement(stmt,2,str);
		this->setStringToStatement(stmt,3,str);
	}

	int result;
	std::vector<Device> devices;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Device device;
			device.setID(sqlite3_column_int(stmt,0));
			device.setGroupID(sqlite3_column_int(stmt,1));
			device.setConfigID(sqlite3_column_int(stmt,2));
			device.setRestoreConfigID(sqlite3_column_int(stmt,3));
			device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
			device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
			device.setCreation(sqlite3_column_int(stmt,6));
			device.setUpdated(sqlite3_column_int(stmt,7));
			device.setContacted(sqlite3_column_int(stmt,8));
			device.setLastBackup(sqlite3_column_int(stmt,9));
			device.setLastRestore(sqlite3_column_int(stmt,10));
			device.setLocalChange(sqlite3_column_int(stmt,11));
			device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
			device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
			device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
			device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
			device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
			device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
			device.setCommands(this->getDeviceCommands(device.getID()));
			device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
			device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
			device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
			device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
			device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
			device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
			device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
			device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
			device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
			device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
			device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
			device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
			device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
			device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
			device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
			device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
			devices.push_back(device);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return devices;
}

std::vector<Device> DataBase::getGroupDevices(const int id)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE groupID = ? ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	this->setIntToStatement(stmt,1,id);

	int result;
	std::vector<Device> devices;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Device device;
			device.setID(sqlite3_column_int(stmt,0));
			device.setGroupID(sqlite3_column_int(stmt,1));
			device.setConfigID(sqlite3_column_int(stmt,2));
			device.setRestoreConfigID(sqlite3_column_int(stmt,3));
			device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
			device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
			device.setCreation(sqlite3_column_int(stmt,6));
			device.setUpdated(sqlite3_column_int(stmt,7));
			device.setContacted(sqlite3_column_int(stmt,8));
			device.setLastBackup(sqlite3_column_int(stmt,9));
			device.setLastRestore(sqlite3_column_int(stmt,10));
			device.setLocalChange(sqlite3_column_int(stmt,11));
			device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
			device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
			device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
			device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
			device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
			device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
			device.setCommands(this->getDeviceCommands(device.getID()));
			device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
			device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
			device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
			device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
			device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
			device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
			device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
			device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
			device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
			device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
			device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
			device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
			device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
			device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
			device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
			device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
			devices.push_back(device);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return devices;
}

std::vector<Device> DataBase::getConfigurationDevices(const int id)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id, groupID, configID, lastRestoreConfigID, configMode, status, creation, updated, contacted, lastBackup, lastRestore, localChange, ip, SHA, name, description, actionPeriod, configFileName, build, upTime, release, swapUsed, maxUsers, licenseID, systemLoad, guiVersion, freeMemory, pepsVersion, customerName, partitionVar, partitionRoot, partitionHome, installedMemory, hardwareDescription FROM device WHERE configID = ? ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	this->setIntToStatement(stmt,1,id);

	int result;
	std::vector<Device> devices;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Device device;
			device.setID(sqlite3_column_int(stmt,0));
			device.setGroupID(sqlite3_column_int(stmt,1));
			device.setConfigID(sqlite3_column_int(stmt,2));
			device.setRestoreConfigID(sqlite3_column_int(stmt,3));
			device.setConfigMode((DeviceConfigMode)sqlite3_column_int(stmt,4));
			device.setStatus((DeviceStatus)sqlite3_column_int(stmt,5));
			device.setCreation(sqlite3_column_int(stmt,6));
			device.setUpdated(sqlite3_column_int(stmt,7));
			device.setContacted(sqlite3_column_int(stmt,8));
			device.setLastBackup(sqlite3_column_int(stmt,9));
			device.setLastRestore(sqlite3_column_int(stmt,10));
			device.setLocalChange(sqlite3_column_int(stmt,11));
			device.setIp(std::string((char*)sqlite3_column_text(stmt,12)));
			device.setSHA(std::string((char*)sqlite3_column_text(stmt,13)));
			device.setName(std::string((char*)sqlite3_column_text(stmt,14)));
			device.setDescription(std::string((char*)sqlite3_column_text(stmt,15)));
			device.setActionPeriod(std::string((char*)sqlite3_column_text(stmt,16)));
			device.setConfigFileName(std::string((char*)sqlite3_column_text(stmt,17)));
			device.setCommands(this->getDeviceCommands(device.getID()));
			device.setBuild(std::string((char*)sqlite3_column_text(stmt,18)));
			device.setUpTime(std::string((char*)sqlite3_column_text(stmt,19)));
			device.setRelease(std::string((char*)sqlite3_column_text(stmt,20)));
			device.setSwapUsed(std::string((char*)sqlite3_column_text(stmt,21)));
			device.setMaxUsers(std::string((char*)sqlite3_column_text(stmt,22)));
			device.setLicenseID(std::string((char*)sqlite3_column_text(stmt,23)));
			device.setSystemLoad(std::string((char*)sqlite3_column_text(stmt,24)));
			device.setGuiVersion(std::string((char*)sqlite3_column_text(stmt,25)));
			device.setFreeMemory(std::string((char*)sqlite3_column_text(stmt,26)));
			device.setPepsVersion(std::string((char*)sqlite3_column_text(stmt,27)));
			device.setCustomerName(std::string((char*)sqlite3_column_text(stmt,28)));
			device.setPartitionVar(std::string((char*)sqlite3_column_text(stmt,29)));
			device.setPartitionRoot(std::string((char*)sqlite3_column_text(stmt,30)));
			device.setPartitionHome(std::string((char*)sqlite3_column_text(stmt,31)));
			device.setInstalledMemory(std::string((char*)sqlite3_column_text(stmt,32)));
			device.setHardwareDescription(std::string((char*)sqlite3_column_text(stmt,33)));
			devices.push_back(device);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return devices;
}

void DataBase::removeDevice(const int id)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		this->removeDeviceCommands(id);
		this->removeDeviceLogs(id);

		char buffer[512];
		sprintf(buffer,"DELETE FROM device WHERE id=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::addDeviceCommand(const Command& command)
{
	char buffer[2048];
	sprintf(buffer,"INSERT INTO deviceCommand(id,cindex,command,arguments) VALUES(?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,2048,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,command.getID());
	this->setIntToStatement(stmt,2,this->nextDeviceCommands(command.getID()));
	this->setStringToStatement(stmt,3,command.getCommand());
	std::string arguments = command.argumentsToString();
	this->setStringToStatement(stmt,4,arguments);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->resetDeviceSHA(command.getID());
}

void DataBase::updateDeviceCommand(const Command& command)
{
	char buffer[2048];
	sprintf(buffer,"UPDATE deviceCommand SET command=?, arguments=? where id=? AND cindex=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,2048,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setStringToStatement(stmt,1,command.getCommand());
	std::string arguments = command.argumentsToString();
	this->setStringToStatement(stmt,2,arguments);
	this->setIntToStatement(stmt,3,command.getID());
	this->setIntToStatement(stmt,4,command.getIndex());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->resetDeviceSHA(command.getID());
}

bool DataBase::existDeviceCommand(const int id, const unsigned int cindex)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM deviceCommand WHERE id=? AND cindex=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);
	this->setIntToStatement(stmt,2,cindex);

	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
	{
		return false;
	}
	else if(result == SQLITE_ROW)
	{
		return true;
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

Command DataBase::getDeviceCommand(const int id, const unsigned int cindex)
{
	char buffer[512];
	sprintf(buffer,"SELECT command,arguments FROM deviceCommand WHERE id=? AND cindex=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);
	this->setIntToStatement(stmt,2,cindex);

	int result = sqlite3_step(stmt);

	Command command;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("Device command not found."));
	}
	else if(result == SQLITE_ROW)
	{
		command.setID(id);
		command.setIndex(cindex);
		command.setCommand(std::string((char*)sqlite3_column_text(stmt,0)));
		command.argumentsFromString(std::string((char*)sqlite3_column_text(stmt,1)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return command;
}

std::vector<Command> DataBase::getDeviceCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT cindex,command,arguments FROM deviceCommand WHERE id=? ORDER BY cindex");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result;
	std::vector<Command> commands;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Command command;
			command.setID(id);
			command.setIndex(sqlite3_column_int(stmt,0));
			command.setCommand(std::string((char*)sqlite3_column_text(stmt,1)));
			command.argumentsFromString(std::string((char*)sqlite3_column_text(stmt,2)));
			commands.push_back(command);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	return commands;
}

void DataBase::switchDeviceCommandIndex(const int id, const unsigned int cindex1, const unsigned int cindex2)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		char buffer[512];
		sprintf(buffer,"UPDATE deviceCommand SET cindex=? WHERE id=? AND cindex=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,((unsigned int)-1));
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,cindex1);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE deviceCommand SET cindex=? WHERE id=? AND cindex=?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,cindex1);
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,cindex2);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE deviceCommand SET cindex=? WHERE id=? AND cindex=?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,cindex2);
		this->setIntToStatement(stmt,2,id);
		this->setIntToStatement(stmt,3,((unsigned int)-1));

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->resetDeviceSHA(id);

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::removeDeviceCommand(const int id, const unsigned int cindex)
{
	try
	{
		this->executeSql("BEGIN TRANSACTION");

		char buffer[512];
		sprintf(buffer,"DELETE FROM deviceCommand WHERE id=? AND cindex=?");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);
		this->setIntToStatement(stmt,2,cindex);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		sprintf(buffer,"UPDATE deviceCommand SET cindex=cindex-1 WHERE id=? AND cindex>?");

		stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->setIntToStatement(stmt,1,id);
		this->setIntToStatement(stmt,2,cindex);

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		this->resetDeviceSHA(id);

		this->executeSql("COMMIT TRANSACTION");
	}
	catch(...)
	{
		this->executeSql("ROLLBACK TRANSACTION");
		throw;
	}
}

void DataBase::removeDeviceCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM deviceCommand WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->resetDeviceSHA(id);
}

unsigned int DataBase::getGroupDevicesCount(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT COUNT(id) FROM device WHERE groupID=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
	{
		return 0;
	}
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0);
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

unsigned int DataBase::getConfigurationDevicesCount(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT COUNT(id) FROM device WHERE configID=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
	{
		return 0;
	}
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0);
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

void DataBase::setStatusDevicesWithConfiguration(const int id, const DeviceStatus status)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE device SET status=? WHERE configID=? AND status=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,status);
	this->setIntToStatement(stmt,2,id);
	this->setIntToStatement(stmt,3,DS_SYNCHRONIZED);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::addLog(const Log& log, bool force)
{
	std::vector<Log> logs = this->getLastLogs(log.getDeviceID(), ACS_LL_DEBUG, 0, 1);
	if(force || logs.empty() || logs[0].getMessage().compare(log.getMessage()) != 0)
	{
		char buffer[4096];
		sprintf(buffer,"INSERT INTO log(level,deviceID,date,ip,name,license,release,customer,command,result,message) VALUES(?,?,?,?,?,?,?,?,?,?,?)");

		sqlite3_stmt* stmt = NULL;
		if(sqlite3_prepare_v2(dbFile,buffer,2048,&stmt,NULL) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		time_t current;
		time(&current);
		this->setIntToStatement(stmt,1,log.getLevel());
		this->setIntToStatement(stmt,2,log.getDeviceID());
		this->setIntToStatement(stmt,3,current);
		this->setStringToStatement(stmt,4,log.getIp());
		this->setStringToStatement(stmt,5,log.getName());
		this->setStringToStatement(stmt,6,log.getLicense());
		this->setStringToStatement(stmt,7,log.getRelease());
		this->setStringToStatement(stmt,8,log.getCustomer());
		this->setStringToStatement(stmt,9,log.getCommand());
		this->setStringToStatement(stmt,10,log.getResult());
		this->setStringToStatement(stmt,11,log.getMessage());

		if(sqlite3_step(stmt) != SQLITE_DONE)
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}

		if(sqlite3_finalize(stmt) != SQLITE_OK)
		{
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}
}

unsigned int DataBase::getLastLogsCount()
{
	char buffer[512];
	sprintf(buffer,"SELECT COUNT(id) FROM log");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
	{
		return 0;
	}
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0);
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

std::vector<Log> DataBase::getLastLogs(const int level, const int offset, const int limit)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,level,deviceID,date,ip,name,license,release,customer,command,result,message FROM log WHERE level >= ? ORDER BY id DESC LIMIT ? OFFSET ?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,level);
	this->setIntToStatement(stmt,2,limit);
	this->setIntToStatement(stmt,3,offset);

	int result;
	std::vector<Log> logs;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Log log;
			log.setID(sqlite3_column_int(stmt,0));
			log.setLevel((LogLevel)sqlite3_column_int(stmt,1));
			log.setDeviceID(sqlite3_column_int(stmt,2));
			log.setDate(sqlite3_column_int(stmt,3));
			log.setIp(std::string((char*)sqlite3_column_text(stmt,4)));
			log.setName(std::string((char*)sqlite3_column_text(stmt,5)));
			log.setLicense(std::string((char*)sqlite3_column_text(stmt,6)));
			log.setRelease(std::string((char*)sqlite3_column_text(stmt,7)));
			log.setCustomer(std::string((char*)sqlite3_column_text(stmt,8)));
			log.setCommand(std::string((char*)sqlite3_column_text(stmt,9)));
			log.setResult(std::string((char*)sqlite3_column_text(stmt,10)));
			log.setMessage(std::string((char*)sqlite3_column_text(stmt,11)));
			logs.push_back(log);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	return logs;
}

unsigned int DataBase::getLastLogsCount(const int deviceID)
{
	char buffer[512];
	sprintf(buffer,"SELECT COUNT(id) FROM log WHERE deviceID = ?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,deviceID);

	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
	{
		return 0;
	}
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0);
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

std::vector<Log> DataBase::getLastLogs(const int deviceID, const int level, const int offset, const int limit)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,level,deviceID,date,ip,name,license,release,customer,command,result,message FROM log WHERE deviceID = ? AND level >= ? ORDER BY id DESC LIMIT ? OFFSET ?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,deviceID);
	this->setIntToStatement(stmt,2,level);
	this->setIntToStatement(stmt,3,limit);
	this->setIntToStatement(stmt,4,offset);

	int result;
	std::vector<Log> logs;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			Log log;
			log.setID(sqlite3_column_int(stmt,0));
			log.setLevel((LogLevel)sqlite3_column_int(stmt,1));
			log.setDeviceID(sqlite3_column_int(stmt,2));
			log.setDate(sqlite3_column_int(stmt,3));
			log.setIp(std::string((char*)sqlite3_column_text(stmt,4)));
			log.setName(std::string((char*)sqlite3_column_text(stmt,5)));
			log.setLicense(std::string((char*)sqlite3_column_text(stmt,6)));
			log.setRelease(std::string((char*)sqlite3_column_text(stmt,7)));
			log.setCustomer(std::string((char*)sqlite3_column_text(stmt,8)));
			log.setCommand(std::string((char*)sqlite3_column_text(stmt,9)));
			log.setResult(std::string((char*)sqlite3_column_text(stmt,10)));
			log.setMessage(std::string((char*)sqlite3_column_text(stmt,11)));
			logs.push_back(log);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	return logs;
}

void DataBase::removeLog(const int logID)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM log WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,logID);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::removeUntilLogs(const time_t date)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM log WHERE data<?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,date);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::removeDeviceLogs(const int deviceID)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM log WHERE deviceID=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,deviceID);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

User DataBase::createUser(const User& user)
{
	char buffer[4096];
	sprintf(buffer,"INSERT INTO suser(type,name,creation,updated,login,password) VALUES(?,?,?,?,?,?)");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,user.getType());
	this->setStringToStatement(stmt,2,user.getName());
	this->setIntToStatement(stmt,3,current);
	this->setIntToStatement(stmt,4,current);
	this->setStringToStatement(stmt,5,user.getLogin());
	this->setStringToStatement(stmt,6,user.getPassword());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return this->getUser(user.getLogin());
}

void DataBase::updateUser(const User& user)
{
	char buffer[4096];
	sprintf(buffer,"UPDATE suser SET type=?, name=?, creation=?, updated=?, login=?, password=? WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,4096,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	time_t current;
	time(&current);
	this->setIntToStatement(stmt,1,user.getType());
	this->setStringToStatement(stmt,2,user.getName());
	this->setIntToStatement(stmt,3,user.getCreation());
	this->setIntToStatement(stmt,4,current);
	this->setStringToStatement(stmt,5,user.getLogin());
	this->setStringToStatement(stmt,6,user.getPassword());
	this->setIntToStatement(stmt,7,user.getID());

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

bool DataBase::existsUser(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM suser WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;

}

bool DataBase::existsUser(const std::string& login)
{
	char buffer[512];
	sprintf(buffer,"SELECT id FROM suser WHERE LOWER(login)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = login;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		exists = false;
	else if(result == SQLITE_ROW)
		exists = true;
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return exists;
}

User DataBase::getUser(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,type,name,creation,updated,login,password FROM suser WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	int result = sqlite3_step(stmt);

	User user;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("User not found."));
	}
	else if(result == SQLITE_ROW)
	{
		user.setID(sqlite3_column_int(stmt,0));
		user.setType((UserType)sqlite3_column_int(stmt,1));
		user.setName(std::string((char*)sqlite3_column_text(stmt,2)));
		user.setCreation(sqlite3_column_int(stmt,3));
		user.setUpdated(sqlite3_column_int(stmt,4));
		user.setLogin(std::string((char*)sqlite3_column_text(stmt,5)));
		user.setPassword(std::string((char*)sqlite3_column_text(stmt,6)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return user;
}

User DataBase::getUser(const std::string& login)
{
	char buffer[512];
	sprintf(buffer,"SELECT id,type,name,creation,updated,login,password FROM suser WHERE LOWER(login)=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	std::string str = login;
	std::transform(str.begin(),str.end(),str.begin(),::tolower);

	this->setStringToStatement(stmt,1,str);

	int result = sqlite3_step(stmt);

	User user;
	if(result == SQLITE_DONE)
	{
		Throw(rgcpp::SQLException("User not found."));
	}
	else if(result == SQLITE_ROW)
	{
		user.setID(sqlite3_column_int(stmt,0));
		user.setType((UserType)sqlite3_column_int(stmt,1));
		user.setName(std::string((char*)sqlite3_column_text(stmt,2)));
		user.setCreation(sqlite3_column_int(stmt,3));
		user.setUpdated(sqlite3_column_int(stmt,4));
		user.setLogin(std::string((char*)sqlite3_column_text(stmt,5)));
		user.setPassword(std::string((char*)sqlite3_column_text(stmt,6)));
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return user;
}

std::vector<User> DataBase::getUsers()
{
	char buffer[1024];
	sprintf(buffer,"SELECT id,type,name,creation,updated,login,password FROM suser ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));


	int result;
	std::vector<User> users;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			User user;
			user.setID(sqlite3_column_int(stmt,0));
			user.setType((UserType)sqlite3_column_int(stmt,1));
			user.setName(std::string((char*)sqlite3_column_text(stmt,2)));
			user.setCreation(sqlite3_column_int(stmt,3));
			user.setUpdated(sqlite3_column_int(stmt,4));
			user.setLogin(std::string((char*)sqlite3_column_text(stmt,5)));
			user.setPassword(std::string((char*)sqlite3_column_text(stmt,6)));
			users.push_back(user);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return users;
}

std::vector<User> DataBase::getUsers(int type)
{
	char buffer[1024];
	sprintf(buffer,"SELECT id,type,name,creation,updated,login,password FROM suser WHERE type=? ORDER BY name");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,1024,&stmt,NULL) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	this->setIntToStatement(stmt,1,type);

	int result;
	std::vector<User> users;
	while((result = sqlite3_step(stmt)) != SQLITE_DONE)
	{
		if(result == SQLITE_ROW)
		{
			User user;
			user.setID(sqlite3_column_int(stmt,0));
			user.setType((UserType)sqlite3_column_int(stmt,1));
			user.setName(std::string((char*)sqlite3_column_text(stmt,2)));
			user.setCreation(sqlite3_column_int(stmt,3));
			user.setUpdated(sqlite3_column_int(stmt,4));
			user.setLogin(std::string((char*)sqlite3_column_text(stmt,5)));
			user.setPassword(std::string((char*)sqlite3_column_text(stmt,6)));
			users.push_back(user);
		}
		else
		{
			sqlite3_finalize(stmt);
			Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
		}
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return users;
}

void DataBase::removeUser(const int id)
{
	char buffer[512];
	sprintf(buffer,"DELETE FROM suser WHERE id=?");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	if(sqlite3_step(stmt) != SQLITE_DONE)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	if(sqlite3_finalize(stmt) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::checkDefaults()
{
	if(!this->existsConfiguration(0))
		this->executeSql("INSERT INTO configuration(id,rwan,rusers,name,creation,updated,description,configFileName,SHA,cfType,cfReboot,cfRelease,cfCreation,cfLicenseID,cfVoipSounds,cfDescription) VALUES(0,0,0,'default',0,0,'default configuration','','','','','','','','','')");

	if(!this->existsGroup(0))
		this->executeSql("INSERT INTO dgroup(id,name,creation,updated,description) VALUES(0,'default',0,0,'Default Group')");
}

DataBase::DataBase() : dbFile(NULL)
{
	LOG_INFO_STR("Creating DataBase...");

	sqlite3_initialize();
	sqlite3_open((ACSConfig::getDataBaseDirectory() + "database.db").c_str(),&dbFile);

	initDataBaseTables();

	LOG_INFO_STR("DataBase Created!");
}

void DataBase::initDataBaseTables()
{
	this->executeSql("PRAGMA foreign_keys = ON;");
	this->executeSql("PRAGMA case_sensitive_like=ON;");

	this->executeSql("CREATE TABLE IF NOT EXISTS configuration(id INTEGER PRIMARY KEY AUTOINCREMENT,"
			"rwan INTEGER, "
			"rusers INTEGER, "
			"name VARCHAR(256) UNIQUE, "
			"creation INTEGER, "
			"updated INTEGER, "
			"description VARCHAR(512), "
			"configFileName VARCHAR(512),"
			"SHA VARCHAR(64), "
			"cfType VARCHAR(32),"
			"cfReboot VARCHAR(16),"
			"cfRelease VARCHAR(32),"
			"cfCreation VARCHAR(32),"
			"cfLicenseID VARCHAR(32),"
			"cfVoipSounds VARCHAR(16),"
			"cfDescription VARCHAR(512))");

	this->executeSql("CREATE TABLE IF NOT EXISTS dgroup(id INTEGER PRIMARY KEY AUTOINCREMENT,"
			"name VARCHAR(256) UNIQUE, "
			"creation INTEGER, "
			"updated INTEGER, "
			"description VARCHAR(512))");

	this->executeSql("CREATE TABLE IF NOT EXISTS configurationCommand(id INTEGER REFERENCES configuration(id), "
			"cindex UNSIGNED INTEGER, "
			"command VARCHAR(512), "
			"arguments TEXT,"
			"PRIMARY KEY (id, cindex))");

	this->executeSql("CREATE TABLE IF NOT EXISTS device(id INTEGER PRIMARY KEY AUTOINCREMENT,"
			"groupID INTEGER REFERENCES dgroup(id), "
			"configID INTEGER REFERENCES configuration(id), "
			"lastRestoreConfigID INTEGER, "
			"configMode INTEGER, "
			"status INTEGER, "
			"creation INTEGER, "
			"updated INTEGER, "
			"contacted INTEGER, "
			"lastBackup INTEGER, "
			"lastRestore INTEGER, "
			"localChange INTEGER, "
			"ip VARCHAR(15), "
			"SHA VARCHAR(64), "
			"name VARCHAR(256) UNIQUE, "
			"description VARCHAR(512), "
			"actionPeriod VARCHAR(32), "
			"configFileName VARCHAR(512),"
			"build VARCHAR(64),"
			"upTime VARCHAR(64),"
			"release VARCHAR(64),"
			"swapUsed VARCHAR(64),"
			"maxUsers VARCHAR(16),"
			"licenseID VARCHAR(64),"
			"systemLoad VARCHAR(128),"
			"guiVersion VARCHAR(32),"
			"freeMemory VARCHAR(64),"
			"pepsVersion VARCHAR(32),"
			"customerName VARCHAR(512),"
			"partitionVar VARCHAR(128),"
			"partitionRoot VARCHAR(128),"
			"partitionHome VARCHAR(128),"
			"installedMemory VARCHAR(64),"
			"hardwareDescription VARCHAR(512))");

	this->executeSql("CREATE TABLE IF NOT EXISTS deviceCommand(id INTEGER REFERENCES device(id), "
			"cindex UNSIGNED INTEGER, "
			"command VARCHAR(512), "
			"arguments TEXT,"
			"PRIMARY KEY (id, cindex))");


	this->executeSql("CREATE TABLE IF NOT EXISTS log(id INTEGER PRIMARY KEY AUTOINCREMENT,"
			"deviceID INTEGER, "
			"level INTEGER, "
			"date INTEGER, "
			"ip VARCHAR(15), "
			"name VARCHAR(256), "
			"license VARCHAR(128), "
			"release VARCHAR(32), "
			"customer VARCHAR(128), "
			"command VARCHAR(254), "
			"result VARCHAR(128), "
			"message VARCHAR(1024))");

	this->executeSql("CREATE TABLE IF NOT EXISTS suser(id INTEGER PRIMARY KEY AUTOINCREMENT,"
			"type INTEGER, "
			"name VARCHAR(256), "
			"creation INTEGER, "
			"updated INTEGER, "
			"login VARCHAR(32) UNIQUE,"
			"password VARCHAR(32))");

	if(this->getUsers().empty())
	{
		User user;
		user.setName("User Administrator");
		user.setLogin("admin");
		user.setPassword("root",false);
		user.setType(ACS_USER_NORMAL);
		this->createUser(user);
	}
}

void DataBase::executeSql(const std::string& sql)
{
	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,sql.c_str(),sql.size(),&stmt,NULL)
			!= SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	if(sqlite3_step(stmt) != SQLITE_DONE)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));

	if(sqlite3_finalize(stmt) != SQLITE_OK)
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
}

void DataBase::setIntToStatement(sqlite3_stmt* stmt, const unsigned int cindex, const int value)
{
	if(sqlite3_bind_int(stmt,cindex,value) != SQLITE_OK)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

void DataBase::setDoubleToStatement(sqlite3_stmt* stmt, const unsigned int cindex, const double value)
{
	if(sqlite3_bind_double(stmt,cindex,value) != SQLITE_OK)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(std::string("DataBase::setDoubleToStatement: ")+sqlite3_errmsg(dbFile)));
	}
}

void DataBase::setStringToStatement(sqlite3_stmt* stmt, const unsigned int cindex, const std::string& value)
{
	if(sqlite3_bind_text(stmt,cindex,value.c_str(),value.size(),SQLITE_STATIC)
			!= SQLITE_OK)
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}
}

unsigned int DataBase::nextConfigurationCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT cindex FROM configurationCommand WHERE id=? ORDER BY cindex DESC LIMIT 1");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		return 0;
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0) + 1;
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

unsigned int DataBase::nextDeviceCommands(const int id)
{
	char buffer[512];
	sprintf(buffer,"SELECT cindex FROM deviceCommand WHERE id=? ORDER BY cindex DESC LIMIT 1");

	sqlite3_stmt* stmt = NULL;
	if(sqlite3_prepare_v2(dbFile,buffer,512,&stmt,NULL) != SQLITE_OK)
	{
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	this->setIntToStatement(stmt,1,id);

	bool exists = false;
	int result = sqlite3_step(stmt);

	if(result == SQLITE_DONE)
		return 0;
	else if(result == SQLITE_ROW)
	{
		return sqlite3_column_int(stmt,0) + 1;
	}
	else
	{
		sqlite3_finalize(stmt);
		Throw(rgcpp::SQLException(sqlite3_errmsg(dbFile)));
	}

	return 0;
}

}
